package Application.Tool;

import Application.AppJoint;
import Application.Controller.TexturePenSettingsController;
import Application.Mask.MaskManager;
import javafx.scene.Parent;
import javafx.fxml.FXMLLoader;
import Application.LayerImage.LayerImage;
import javafx.scene.input.MouseEvent;
import Application.Layer.Layer;
import Application.Layer.LayerDelegate;

public class TexturePen extends Tool {
    private Parent root;
    private static TexturePen ins = new TexturePen();

    // 笔尖
    private LayerImage mask;
    // 大小
    private int size = 32;
    // 纹理
    private LayerImage texture;
    // 纹理原点
    private int originx = 0;
    private int originy = 0;
    // 纹理缩放
    private double scale = 1.0;
    // 点击点
    private int cx = 0;
    private int cy = 0;

    private TexturePen() {
        super();
        // 加载本工具的工具设置
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("/View/texturePenSettings.fxml"));
            root = loader.load();

            AppJoint.getInstance().loadMasksToComboBox(
                    ((TexturePenSettingsController)loader.getController()).getCombo()
            );

            //System.out.println(((TexturePenSettingsController)loader.getController()).getXXX().getStyle());
        } catch(Exception e) {
            e.printStackTrace();
        }

        mask = MaskManager.getInstance().getMaskByName("test");
    }

    private int blend(int oldColor, int textureColor, int i, int j, int gray) {
        int a0 = (oldColor >> 24) & 0xff;
        int r0 = (oldColor & 0x00ff0000) >> 16;
        int g0 = (oldColor & 0x0000ff00) >> 8;
        int b0 = (oldColor & 0x000000ff);
        int r1 = (textureColor & 0x00ff0000) >> 16;
        int g1 = (textureColor & 0x0000ff00) >> 8;
        int b1 = (textureColor & 0x000000ff);

        int a = a0 + gray;
        if(a > 255) {
            a = 255;
        }
        int r = (gray * r1 + (255 - gray) * r0) / 255;
        int g = (gray * g1 + (255 - gray) * g0) / 255;
        int b = (gray * b1 + (255 - gray) * b0) / 255;

        //cache[i][j] = a;

        return (a << 24) | (r << 16) | (g << 8) | b;
    }

    public static TexturePen getInstance() {
        return ins;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public void setMask(String name) {
        this.mask = MaskManager.getInstance().getMaskByName(name);
    }

    public void setTexture(LayerImage img) {
        this.texture = img;
    }

    public void setOrigin(int ox, int oy) {
        this.originx = ox;
        this.originy = oy;
    }

    public void setScale(double scale) {
        this.scale = scale;
    }

    @Override public void onMouseMove(MouseEvent e) {
        double pixelx =
                e.getX() / AppJoint.getInstance().getImageView().getFitWidth() * AppJoint.getInstance().getCanvasWidth();
        double pixely =
                e.getY() / AppJoint.getInstance().getImageView().getFitHeight() * AppJoint.getInstance().getCanvasHeight();
        Layer activeLayer = LayerDelegate.getInstance().getLayerById(AppJoint.getInstance().getActiveLayerId());

        for(int i = -size / 2; i < size / 2; i++) {
            for(int j = -size / 2; j < size / 2; j++) {
                // 实际像素位置
                int imgx = (int)pixelx + i;
                int imgy = (int)pixely + j;
                if(imgx >= 0 && imgx < AppJoint.getInstance().getCanvasWidth() && imgy >= 0 && imgy < AppJoint.getInstance().getCanvasHeight()) {
                    // 蒙版像素位置
                    int maskx = (i + size / 2) * MaskManager.MASK_SIZE / size;
                    int masky = (j + size / 2) * MaskManager.MASK_SIZE / size;
                    // 蒙版灰度
                    int gray = (mask.getPixelArgb(maskx, masky) & 255);

                    //if(cache[imgx][imgy] < 255) {
                        int deltaX = imgx - cx;
                        int deltaY = imgy - cy;
                        int w = texture.getWidth();
                        int h = texture.getHeight();
                        int textureColor = texture.getPixelArgb(
                                (int)(((originx + deltaX + w) % w) / scale % w),
                                (int)(((originy + deltaY + h) % h) / scale % h)
                        );

                        int oldColor = activeLayer.getArgb(imgx, imgy);
                        int newColor = this.blend(oldColor, textureColor, imgx, imgy, gray);

                        activeLayer.setArgb(imgx, imgy, newColor);
                        LayerDelegate.getInstance().refreshSingle(imgx, imgy);
                    //}


                }
            }
        }
    }

    @Override public void onMouseDown(MouseEvent e) {
        cx = (int)(e.getX() / AppJoint.getInstance().getImageView().getFitWidth() * AppJoint.getInstance().getCanvasWidth());
        cy = (int)(e.getY() / AppJoint.getInstance().getImageView().getFitHeight() * AppJoint.getInstance().getCanvasHeight());

        int width = AppJoint.getInstance().getCanvasWidth();
        int height = AppJoint.getInstance().getCanvasHeight();
        //cache = new int[width][height];
        onMouseMove(e);
    }

    @Override public void onMouseUp(MouseEvent e) {

    }

    @Override public Parent getToolSettings() {
        return root;
    }
}
